#include "copyright.h"
#include "system.h"
#include "console.h"
#include "machine.h"
#include "synchconsole.h"
#include "addrspace.h"
#include "synch.h"
#include "userthread.h"

int do_UserThreadCreate(int f, int arg){
	
	// Threads
	
	UserThreadArgs *f_Args = new UserThreadArgs;
	
	int thread_id = currentThread->space->threadBitMap->Find();
	//printf("thread_id : %d.\n", thread_id);
	if (thread_id == -1){ return -1;} // si pas de place dans le Bitmap

	f_Args->f = (int)f;
	f_Args->arg =(int)arg;
	
	Thread *newThread = new Thread ("f(arg)");
	if (newThread == NULL){ return -1;}
	newThread->thread_id = thread_id;
	//currentThread->space->threadBitMap->Mark(thread_id);
	newThread->SaveUserState();

	newThread->Fork(StartUserThread,(int)f_Args);
	// On bloque le semaphore de thread_id
	void* sem = newThread->space->sem_thread[thread_id];
	((Semaphore*)sem)->P();
	//verification des Arguements
//	printf("f_Args->f %d\n",f_Args->f);
//	printf("f_Args->arg %d\n",f_Args->arg);
	
	// on incremente un compteur de thread  a la creation (a faire)
	
return thread_id;
	
}

void do_UserThreadExit(){
	//on decremente le compteur de thread de creation (a faire ) 
	//currentThread->RestoreUserState();
	//currentThread->space->threadBitMap->Print();
		currentThread->RestoreUserState();	// load page table register
		// On libere l'emplacement correspondant dans le bitMap
		currentThread->space->threadBitMap->Clear(currentThread->thread_id);
		// On libere la place
		void* sem = currentThread->space->sem_thread[currentThread->thread_id];
		((Semaphore*)sem)->V();
		
		// On termine le thread courant
		currentThread->Finish();
	//currentThread->space->threadBitMap->Print();
}

/**
 * do_UserThreadJoin attend la fin du thread tid
 */
void do_UserThreadJoin(int tid){
	if (tid > 0) {
		if(currentThread->space->threadBitMap->Test(tid))
		{
		//	printf("attente du thread %d \n", tid);
			void* sem = currentThread->space->sem_thread[tid];
			((Semaphore*)sem)->P();
			((Semaphore*)sem)->V();
			//printf("attente du thread %d OK \n", tid);
			
		}
	}
}

static void StartUserThread(int f){
	
	//currentThread->space->InitRegisters();	// set the initial register values

	UserThreadArgs *f_Args = (UserThreadArgs *) f;
	
//	 printf("f_Args->f %d\n",f_Args->f);
//	printf("f_Args->arg %d\n",f_Args->arg);
//	currentThread->space->threadBitMap->Print();

	currentThread->space->do_InitRegister(currentThread->thread_id,(f_Args->f),(f_Args->arg));

	//currentThread->space->RestoreState ();
	int r6 = machine->ReadRegister(23);
	machine->WriteRegister(31,r6);
	//printf("RRRRRRRR66666666666666666 ======== %d\n",r6);
	//currentThread->space->threadBitMap->Print();
	machine->Run ();
}

